#include "../Card.h"
#include "../Logic.h"
#include "../Table.h"
#include <algorithm>
#include <assert.h>
#include <vector>
#include <iostream>
#define EVALUATE_TABLE 1
#define GET_GAME_WINNER 1
using namespace std;
int main(void)
{
  Logic logic;
  /*
  Focus on 4-player tests... this is the main game. Add more coverage later if
  needed.
  */
  Table table(4);
  Deck* d = &table.activeCards;
  vector<Player>* p = &table.players;
  logic.setTable(&table);
  /* Get some cards to work with. */
  vector<Player*> players(100);
  for(int i = 0; i < players.size(); ++i)
    players.at(i) = new Player();
  int c = 0;
  Card ha(  hearts,   ace, c); ha.setOwner(players.at(c++));
  Card sa(  spades,   ace, c); sa.setOwner(players.at(c++));
  Card d2(diamonds,    _2, c); d2.setOwner(players.at(c++));
  Card s2(  spades,    _2, c); s2.setOwner(players.at(c++));
  Card c2(   clubs,    _2, c); c2.setOwner(players.at(c++));
  Card c3(   clubs,    _3, c); c3.setOwner(players.at(c++));
  Card h3(  hearts,    _3, c); h3.setOwner(players.at(c++));
  Card c4(   clubs,    _4, c); c4.setOwner(players.at(c++));
  Card c5(   clubs,    _5, c); c5.setOwner(players.at(c++));
  Card j0(   clubs, joker, c); j0.setOwner(players.at(c++));
  Card j1(   clubs, joker, c); j1.setOwner(players.at(c++));
  Card j2(   clubs, joker, c); j2.setOwner(players.at(c++));
  Card j3(   clubs, joker, c); j3.setOwner(players.at(c++));
  #if EVALUATE_TABLE
    vector<Player*> result;
    /* Test basic win. */
    d->add(&d2);
    d->add(&c3);
    d->add(&c4);
    d->add(&c5);
    result = logic.evaluateTable();
    assert(result.size() == 1);
    assert(find(result.begin(), result.end(), c5.getOwner()) != result.end());
    /* Test basic war. */
    table.warTime = false;
    d->replace(2, &h3);
    result = logic.evaluateTable();
    assert(result.size() == 2);
    assert(find(result.begin(), result.end(), c3.getOwner()) != result.end());
    assert(find(result.begin(), result.end(), h3.getOwner()) != result.end());
    /* Aces are low during peace. */
    table.warTime = false;
    d->replace(2, &ha);
    #if 1
      cout << "Peaceful Ace setup:";
      d->debugPrint();
    #endif
    result = logic.evaluateTable();
    assert(result.size() == 1);
    assert(find(result.begin(), result.end(), c5.getOwner()) != result.end());
    /* Aces are high during war. */
    table.warTime = true;
    result = logic.evaluateTable();
    assert(result.size() == 1);
    assert(find(result.begin(), result.end(), ha.getOwner()) != result.end());
    /* Make sure a war of aces makes all aces win. */
    table.warTime = true;
    d->replace(0, &sa);
    result = logic.evaluateTable();
    assert(result.size() == 2);
    assert(find(result.begin(), result.end(), ha.getOwner()) != result.end());
    assert(find(result.begin(), result.end(), sa.getOwner()) != result.end());
    /* In peace ace beats joker. */
    d->draw(d->size());
    d->add(&j0);
    d->add(&sa);
    table.warTime = false;
    result = logic.evaluateTable();
    assert(result.size() == 1);
    assert(find(result.begin(), result.end(), sa.getOwner()) != result.end());
    /* In war, ace beats joker. */
    d->add(&ha);
    table.warTime = true;
    result = logic.evaluateTable();
    assert(result.size() == 2);
    assert(find(result.begin(), result.end(), sa.getOwner()) != result.end());
    assert(find(result.begin(), result.end(), ha.getOwner()) != result.end());
    #if 0
      d->debugPrint();
    #endif
    cout << "Logic::evaluateTable() passed all tests."<< endl;
  #endif
  #if GET_GAME_WINNER
    /* Try everyone alive. */
    p->at(0).setOwner(NULL);
    p->at(1).setOwner(NULL);
    p->at(2).setOwner(NULL);
    p->at(3).setOwner(NULL);
    assert(logic.getGameWinner() == -1);
    /* Try first dead. */
    p->at(0).setOwner(&p->at(1));
    assert(logic.getGameWinner() == -1);
    /* Try last player dead. */
    p->at(0).setOwner(NULL);
    p->at(3).setOwner(&p->at(0));
    assert(logic.getGameWinner() == -1);
    /* Try middle player dead. */
    p->at(3).setOwner(NULL);
    p->at(1).setOwner(&p->at(0));
    assert(logic.getGameWinner() == -1);
    /* Try multiple dead players. */
    p->at(0).setOwner(&p->at(2));
    p->at(1).setOwner(&p->at(2));
    assert(logic.getGameWinner() == -1);
    /* Try first player winner. */
    p->at(0).setOwner(NULL);
    p->at(1).setOwner(&p->at(0));
    p->at(2).setOwner(&p->at(0));
    p->at(3).setOwner(&p->at(0));
    assert(logic.getGameWinner() == 0);
    /* Try last player winner. */
    p->at(0).setOwner(&p->at(3));
    p->at(1).setOwner(&p->at(3));
    p->at(2).setOwner(&p->at(3));
    p->at(3).setOwner(NULL);
    assert(logic.getGameWinner() == 3);
    /* Try middle player winner. */
    p->at(0).setOwner(&p->at(2));
    p->at(1).setOwner(&p->at(2));
    p->at(2).setOwner(NULL);
    p->at(3).setOwner(&p->at(2));
    assert(logic.getGameWinner() == 2);
    /* Try everyone dead. */
    p->at(0).setOwner(&p->at(2));
    p->at(1).setOwner(&p->at(2));
    p->at(2).setOwner(&p->at(2));
    p->at(3).setOwner(&p->at(2));
    assert(logic.getGameWinner() == -2);
    cout << "Logic::getGameWinner() passed all tests."<< endl;
  #endif
  return 0;
}
